package cn.lingyangwl.agile.auth.utils;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.StrUtil;
import cn.lingyangwl.agile.model.constants.OAuth2Cons;
import cn.lingyangwl.agile.model.enums.AuthErrorEnum;
import cn.lingyangwl.agile.model.module.auth.OAuth2ParamKeys;
import cn.lingyangwl.framework.tool.core.StringUtils;
import cn.lingyangwl.framework.tool.core.exception.BizException;
import lombok.experimental.UtilityClass;
import org.springframework.http.HttpHeaders;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;

/**
 * OAuth2 端点工具
 * @author shenguangyang
 */
@UtilityClass
public class OAuth2Utils {

	public final String ACCESS_TOKEN_REQUEST_ERROR_URI = "https://datatracker.ietf.org/doc/html/rfc6749#section-5.2";

	public MultiValueMap<String, String> getParameters(HttpServletRequest request) {
		Map<String, String[]> parameterMap = request.getParameterMap();
		MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>(parameterMap.size());
		parameterMap.forEach((key, values) -> {
			if (values.length > 0) {
				for (String value : values) {
					parameters.add(key, value);
				}
			}
		});
		return parameters;
	}

	public static String[] obtainBasicAuthorization(HttpServletRequest request) {
		String clientId;
		String clientSecret;
		// 先从 Header 中获取
		String authorization = request.getHeader(HttpHeaders.AUTHORIZATION);
		authorization = StrUtil.subAfter(authorization, OAuth2Cons.TokenType.BASIC + " ", true);
		if (StringUtils.hasText(authorization)) {
			authorization = Base64.decodeStr(authorization);
			clientId = StrUtil.subBefore(authorization, ":", false);
			clientSecret = StrUtil.subAfter(authorization, ":", false);
			// 再从 Param 中获取
		} else {
			clientId = request.getParameter(OAuth2ParamKeys.CLIENT_ID);
			clientSecret = request.getParameter(OAuth2ParamKeys.CLIENT_SECRET);
		}

		// 如果两者非空，则返回
		if (StrUtil.isNotEmpty(clientId) && StrUtil.isNotEmpty(clientSecret)) {
			return new String[]{clientId, clientSecret};
		}
		return null;
	}

	public static List<String> buildScopes(String scope) {
		return StrUtil.split(scope, ' ');
	}

	public static String getHeaderToken(HttpServletRequest request, String tokenType) {
		String value = request.getHeader(HttpHeaders.AUTHORIZATION);
		if (StringUtils.isEmpty(value)) {
			throw new BizException(AuthErrorEnum.MISS_AUTH_HEADER);
		}
		return OAuth2Cons.TokenType.BASIC.equals(tokenType)
				? Base64.decodeStr(value.replaceAll(tokenType + " ", ""))
				: value.replaceAll(tokenType + " ", "");
	}

}
